package com.plian.system.service.wfTwo;

import com.plian.Tools.CollectionUtil;
import com.plian.Tools.TokenUtil;
import com.plian.Tools.pagedata.PageData;
import com.plian.system.bean.wf.UserPOJO;
import com.plian.system.bean.wf.UserTaskPOJO;
import com.plian.system.config.exception.MyRuntimeException;
import com.plian.system.constant.wf.TaskStateConstant;
import com.plian.system.dao.sys.orgzation.OrgzationDao;
import com.plian.system.helper.wf.SimulationHelper;
import com.plian.system.helper.wf.WorkFlowHelper;
import com.plian.system.model.ObjResult;
import com.plian.system.service.sys.orgzation.OrgzationService;
import com.plian.system.service.sys.user.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

import static com.plian.system.constant.wf.WorkflowConstant.*;

@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
@Slf4j
@Service
@Transactional
public class WorkflowTwoServiceImpl implements WorkflowTwoService {
    @Autowired
    private HistoryService historyService;
    @Autowired
    private WorkFlowHelper workFlowHelper;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private OrgzationService orgzationService;
    @Autowired
    private OrgzationDao orgzationDao;
    @Autowired
    @Qualifier("processEngine")
    private ProcessEngine processEngine;
    @Autowired
    private UserService userService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private SimulationHelper simulationHelper;
    public void startProcessInstanceForBackToStash(String formId, int formType, Map<String, Object> variables, String startUserId) {
        // 保证formId 和 processInstanceId 一一对一
        List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().processInstanceBusinessKey(formId).list();
        if (CollectionUtil.isNotEmpty(list)) {
            return;
        }
        startProcessInstanceByKeyAndTenantId(workFlowHelper.getModelKeyWithFormType(formType), formId, variables, startUserId);
    }
    public void startProcessInstanceByKeyAndTenantId(String processDefinitionKey, String businessKey, Map<String, Object> variables, String startUserId) {
        // 默认当前单位的工作流
        ProcessInstance processInstance;
        // 判断表单是否被发起过
        List<ProcessInstance> list = runtimeService
                .createProcessInstanceQuery()
                .processInstanceBusinessKey(businessKey)
                .list();
        if (CollectionUtil.isNotEmpty(list)) {
            if (list.size() == 1) {
                processInstance = list.get(0);
            } else {
                throw new MyRuntimeException(new ObjResult("当前单据存在多个流程，请联系管理员维护数据库！"));
            }
        } else {
            try {
                String orgId = (String)variables.get(ORGANIZATION_ID);
                PageData groupOrg = orgzationService.getGroupbyId(orgId, orgzationDao.list(null));
                if(groupOrg == null){
                    variables.put(UNIT_ORG_ID, orgId);
                }else {
                    variables.put(UNIT_ORG_ID, groupOrg.getString("id"));
                }

            }catch (Exception e){
                log.error("---> 获取集团id失败");
            }
            processEngine.getIdentityService().setAuthenticatedUserId(startUserId == null ? userService.getCurrentUser().getId() : startUserId);
            processInstance = runtimeService.startProcessInstanceByKeyAndTenantId(processDefinitionKey, businessKey, variables, null);
        }
        Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
        taskService.setAssignee(task.getId(), startUserId == null ? userService.getCurrentUser().getId() : startUserId);
        taskService.setVariableLocal(task.getId(), APPLY_STATE, TaskStateConstant.STATE_NO_APPLY);
    }
    public void goBackToStash(String formId, int formType) {
        //根据formId获取历史流程实例
        HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceBusinessKey(formId).includeProcessVariables().singleResult();

        Map<String, Object> processVariables = processInstance.getProcessVariables();

        String startUserId = processInstance.getStartUserId();

        //删除流程实例
        historyService.deleteHistoricProcessInstance(processInstance.getId());

        //开启新流程
        //校验历史流程是否删除
        List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().processInstanceBusinessKey(formId).list();
        if (list.size() > 0) {
            throw new MyRuntimeException(new ObjResult("原历史流程并未删除"));
        }
        startProcessInstanceForBackToStash(formId, formType, processVariables, startUserId);
        ProcessInstance newProcessInstance = runtimeService
                .createProcessInstanceQuery()
                .processInstanceBusinessKey(formId)
                .singleResult();
        LinkedList<UserTaskPOJO> newProcess;
        try {
            newProcess = simulationHelper.simulation(newProcessInstance, processVariables, true);
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            throw new MyRuntimeException(new ObjResult("保存单据模拟流程异常！"));
        }
        List<UserTaskPOJO> oldProcess = workFlowHelper.getUserTaskListInProcessVariable(processVariables);
        UserTaskPOJO last = oldProcess.get(oldProcess.size() - 1);
        last.setTaskState(TaskStateConstant.STATE_BACK_TO_STASH);
//        last.setFinishTime(new Date());
//        PageData pageData = new PageData();
//        pageData.put("id", TokenUtil.getTokenUserId());
//        last.setUserList(new ArrayList<>(1));
//        last.setUserPOJO(new UserPOJO(userService.findbyid(pageData).getPageData()));
        UserTaskPOJO first = newProcess.get(0);
        PageData pageData01 = new PageData();
        pageData01.put("id", startUserId);
        first.setUserList(new ArrayList<>(1));
        first.setUserPOJO(new UserPOJO(userService.findbyid(pageData01).getPageData()));
        oldProcess.addAll(newProcess);
        workFlowHelper.saveUserTaskListIntoVariable(oldProcess, newProcessInstance.getId());
        List<Task> taskList = taskService.createTaskQuery().processInstanceBusinessKey(formId).active().list();
        if (taskList.size() != 1) {
            throw new MyRuntimeException(new ObjResult("反审核失败！"));
        }
        Task task = taskList.get(0);
        taskService.setAssignee(task.getId(), startUserId);
    }
}
